package com.dsteiner.xelavos.client.controller;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;

import com.dsteiner.widgets.client.IJsUtil;
import com.dsteiner.widgets.client.StringUtil;
import com.dsteiner.widgets.client.Widgets.IButton;
import com.dsteiner.widgets.client.Widgets.IHTML;
import com.dsteiner.widgets.client.Widgets.IImage;
import com.dsteiner.widgets.client.Widgets.ILazyWidget;
import com.dsteiner.widgets.client.Widgets.ISimplePanel;
import com.dsteiner.widgets.client.Widgets.IWidget;
import com.dsteiner.widgets.client.Widgets.WidgetListenerAdapter;
import com.dsteiner.widgets.client.controller.PopupOverlayController;
import com.dsteiner.widgets.client.domain.ModelObject;
import com.dsteiner.widgets.client.event.DataUpdateEvent;
import com.dsteiner.widgets.client.event.EventManagerImpl;
import com.dsteiner.widgets.client.event.MessageEvent;
import com.dsteiner.widgets.client.model.PopupOverlayModel;
import com.dsteiner.widgets.client.rpc.CrudResult;
import com.dsteiner.xelavos.client.ChangeImageWidget.ChangeImageModel;
import com.dsteiner.xelavos.client.ChangeableImage.ChangeableImageModel;
import com.dsteiner.xelavos.client.constants.Constants;
import com.dsteiner.xelavos.client.domain.HasImage;
import com.dsteiner.xelavos.client.domain.HasUser;
import com.dsteiner.xelavos.client.domain.User;
import com.dsteiner.xelavos.client.model.AuthenticationModel;
import com.dsteiner.xelavos.client.model.CreateObjectModel;
import com.dsteiner.xelavos.client.rpc.DataService;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;

public class CreateObjectController {

	public class ImageSuggestions{
		private String text;
		private List<String> imageUrls = new ArrayList<String>();
		
		public ImageSuggestions(String text) {
			this.text = text;
		}
		public ImageSuggestions(String text, List<String> imagetUrls) {
			this(text);
			this.imageUrls = imagetUrls;
		}
		public List<String> getImageUrls() {
			return imageUrls;
		}
		public void setImageUrls(List<String> imageUrls) {
			this.imageUrls = imageUrls;
		}
		public String getText() {
			return text;
		}
		public void add(String imageUrl) {
			imageUrls.add(imageUrl);
		}
	}
	
	private CreateObjectModel createObjectModel;
	private AuthenticationModel authenticationModel;
	private PopupOverlayModel fileUploadPopupOverlayModel;
	private ChangeImageModel changeImageModel;
	private ISimplePanel contentPanel;
	private ChangeableImageModel changeableImageModel;
	private IHTML titleHtml;
	private IImage icon;
	private IButton createObjectButton;
	private IJsUtil jsUtil;
	private com.dsteiner.xelavos.client.controller.ImageSearch imageSearch;

	public void registerAuthenticationModel(AuthenticationModel authenticationModel) {
		this.authenticationModel = authenticationModel;
	}

	public void registerChangeImageLink(final IHTML changeImageLink) {
		changeImageLink.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent event) {
				ModelObject object = createObjectModel.getCreateModelObject();
				String fileUploadUrl = Constants.Util.getFileUploadUrl(object);
				changeImageModel.setActionUrl(fileUploadUrl);
				changeImageModel.setImageUrls(createObjectModel.getImageSuggestions());
				PopupOverlayController.showAtCenter(fileUploadPopupOverlayModel);
			}
		});
	}

	public void registerContentPanel(ISimplePanel contentPanel) {
		this.contentPanel = contentPanel;
	}

	public void registerCreateObjectButton(final IButton createObjectButton) {
		this.createObjectButton = createObjectButton;
		createObjectButton.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent event) {
				jsUtil.trackEvent(Constants.CAT_PUBLISHING, Constants.ACT_CLICKED_ADD_BUTTON);
				IModelObjectBuilder modelObjectBuilder = createObjectModel.getModelObjectBuilder();
				ModelObject modelObjectToCreate = modelObjectBuilder.create();
				if(modelObjectToCreate == null)
					return;
				if(modelObjectToCreate instanceof HasImage){
					String imageId = changeImageModel.getSubmitResult();
					if(imageId == null){
						imageId = Constants.Util.getImageId(changeableImageModel.getUrl());
					}
					((HasImage)modelObjectToCreate).setImageId(imageId);
						
				}
				if(modelObjectToCreate instanceof HasUser){
					User user = authenticationModel.getUser();
					((HasUser)modelObjectToCreate).setUserId(user.getId());
					((HasUser)modelObjectToCreate).setUserFirstName(user.getFirstName());
				}
				createObjectButton.setEnabled(false);
				if(modelObjectToCreate.getId() != null){
					EventManagerImpl.getInstance().fireEvent(new MessageEvent("actualizar datos...", MessageEvent.TYPE_ACTIVITY));
					DataService.Util.getInstance().updateObject(modelObjectToCreate, new AsyncCallback<CrudResult<ModelObject>>(){
						public void onFailure(Throwable caught) {
							EventManagerImpl.getInstance().fireEvent(new MessageEvent("Actualizar fallo - intentelo otra vez"));
							createObjectButton.setEnabled(true);
						}
						public void onSuccess(CrudResult result) {
							createObjectButton.setEnabled(true);
							EventManagerImpl.getInstance().fireEvent(new MessageEvent(null, MessageEvent.TYPE_ACTIVITY));
							ModelObject modelObject = result.getModelObject();
							EventManagerImpl.getInstance().fireEvent(new DataUpdateEvent(modelObject));
						}
					});
				}
				else{
					EventManagerImpl.getInstance().fireEvent(new MessageEvent("publicar nuevos datos...", MessageEvent.TYPE_ACTIVITY));
					DataService.Util.getInstance().createModelObject(modelObjectToCreate, new AsyncCallback<CrudResult<ModelObject>>(){
						public void onFailure(Throwable caught) {
							createObjectButton.setEnabled(true);
							EventManagerImpl.getInstance().fireEvent(new MessageEvent("Publicar fallo - intentelo otra vez"));
						}
						public void onSuccess(CrudResult result) {
							createObjectButton.setEnabled(true);
							EventManagerImpl.getInstance().fireEvent(new MessageEvent(null, MessageEvent.TYPE_ACTIVITY));
							ModelObject modelObject = result.getModelObject();
							EventManagerImpl.getInstance().fireEvent(new DataUpdateEvent(modelObject));
							
							User user = (User) authenticationModel.getUser();
							user.setEntriesCount(user.getEntriesCount()+1);
							EventManagerImpl.getInstance().fireEvent(new DataUpdateEvent(user));
						}
					});
				}
			}
		});
	}

	public void registerCreateObjectModel(final CreateObjectModel createObjectModel) {
		this.createObjectModel = createObjectModel;
		createObjectModel.addPropertyChangeListener("contentWidget", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				updateContentWidget();
			}
		});
		createObjectModel.addPropertyChangeListener("imageSearch", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				doImageSearch();
			}
		});
		createObjectModel.addPropertyChangeListener("title", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				updateTitle();
			}
		});
		createObjectModel.addPropertyChangeListener("icon", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				updateIcon();
			}
		});
		createObjectModel.addPropertyChangeListener("createObjectModel", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				updateImageUrl();
				updateCreateObjectButtonText();
			}
		});
	}

	private void updateCreateObjectButtonText() {
		ModelObject createModelObject = createObjectModel.getCreateModelObject();
		createObjectButton.setText(createModelObject.getId() != null ? "actualizar" : "crear");
	}

	public void registerCreateObjectWidget(ILazyWidget createObjectWidget) {
		createObjectWidget.addWidgetListener(new WidgetListenerAdapter() {
			@Override
			public void onAttach(IWidget widget) {
				createObjectModel.getImageSuggestions().clear();
				changeImageModel.setSubmitResult(null);
				changeImageModel.setSelectedImageUrl(null);
				changeableImageModel.setUrl(null);
				updateContentWidget();
				updateTitle();
				updateIcon();
				updateImageUrl();
				updateCreateObjectButtonText();
			}
		});
	}

	private void updateIcon() {
		AbstractImagePrototype abstractImagePrototype = createObjectModel.getIcon();
		if(abstractImagePrototype != null)
			abstractImagePrototype.applyTo(icon.getImage());
	}

	public void registerChangeImageModel(final ChangeImageModel changeImageModel) {
		this.changeImageModel = changeImageModel;
		changeImageModel.addPropertyChangeListener("submitResult", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				String id = changeImageModel.getSubmitResult();
				if(id != null){
					fileUploadPopupOverlayModel.setVisible(false);
					updateImageUrl();
				}
			}
		});
		changeImageModel.addPropertyChangeListener("selectedImageUrl", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				fileUploadPopupOverlayModel.setVisible(false);
				updateImageUrl();
			}
		});
	}

	public void registerFileUploadPopupOverlayModel(PopupOverlayModel fileUploadPopupOverlayModel) {
		this.fileUploadPopupOverlayModel = fileUploadPopupOverlayModel;
	}

	public void registerIcon(IImage icon) {
		this.icon = icon;
	}
	
	public void registerChangeableImageModel(ChangeableImageModel changeableImageModel) {
		this.changeableImageModel = changeableImageModel;
	}

	public void registerTitleHtml(IHTML titleHtml) {
		this.titleHtml = titleHtml;
	}

	private void updateContentWidget() {
		IWidget contentWidget = createObjectModel.getContentWidget();
		contentPanel.setWidget(contentWidget);
	}
	
	private void updateImageUrl(){
	    
	    String submitImageId = changeImageModel.getSubmitResult();
		if(submitImageId != null){
	    	changeableImageModel.setUrl(Constants.Util.getImageUrl(submitImageId));
	    	return;
	    }
		
		String selectedImageUrl = changeImageModel.getSelectedImageUrl();
		if(selectedImageUrl != null){
			changeableImageModel.setUrl(Constants.Util.getImageUrl(selectedImageUrl));
			return;
		}
	    
		ModelObject createModelObject = createObjectModel.getCreateModelObject();
		if(createModelObject instanceof HasImage && ((HasImage)createModelObject).getImageId() != null){
	    	changeableImageModel.setUrl(Constants.Util.getImageUrl(((HasImage)createModelObject).getImageId()));
	    	return;
		}
	}

	private void doImageSearch() {
		final String imageSearchText = createObjectModel.getImageSearch();
	    if(StringUtil.isEmpty(imageSearchText)){
	    	changeableImageModel.setUrl(null);
	    	return;
	    }
	    
	    imageSearch.searchImages(imageSearchText);
	}

	private void updateTitle() {
		ModelObject createModelObject = createObjectModel.getCreateModelObject();
		String title = createObjectModel.getTitle();
		titleHtml.setVisible(title != null);
		titleHtml.setHTML(createModelObject.getId() != null ? "actualice "+title : "publique "+title);
	}

	public void registerJsUtil(IJsUtil jsUtil) {
		this.jsUtil = jsUtil;
	}
	
	public void registerImageSearch(ImageSearch imageSearch) {
		this.imageSearch = imageSearch;
		imageSearch.addImageSearchCompleteHandler(new ImageSearchCompleteHandler(){
			public void onImageSearchComplete(String imageSearchText, String imageUrl, int currentPageIndex) {
		        String currentImageUrl = changeableImageModel.getUrl();
				if(currentPageIndex == 0 && StringUtil.isEmpty(currentImageUrl))
		        	changeableImageModel.setUrl(imageUrl);
				ImageSuggestions imageSuggestions = null;
				for (ImageSuggestions imageSuggestion : createObjectModel.getImageSuggestions()) {
					if(imageSearchText.equals(imageSuggestion.getText())){
						imageSuggestions = imageSuggestion;
						break;
					}
				}
				if(imageSuggestions == null){
					imageSuggestions = new ImageSuggestions(imageSearchText);
					createObjectModel.getImageSuggestions().add(imageSuggestions);
				}
				
				imageSuggestions.add(imageUrl);
//				count++;
			}
		});
	}
	
}